<template>
  <div :style="{width}"
       class="input-box">
    <div v-if="label"
         :style="{width: labelWidth}"
         class="label">
      {{ label }}
    </div>

    <div :class="{focus, error: errMsg}"
         class="xtx-input">
      <div v-if="icon"
           class="left">
        <i :class="`iconfont icon-` + icon"/>
      </div>
      <slot name="input">
        <input v-model="inputValue"
               :placeholder="placeholder"
               :type="type"
               class="center"
               @focusin="focus = true"
               @focusout="focusOut"
               @input="judge(true)"/>
      </slot>
      <div class="right">
        <slot/>
      </div>
    </div>
  </div>
  <div :style="{width}"
       class="err-msg">
    <div v-if="label"
         :style="{width: labelWidth}"
         class="label">
      {{ label }}
    </div>
    <div v-show="errMsg"
         class="msg">
      <i class="iconfont icon-warning"/>
      {{ errMsg }}
    </div>
  </div>
</template>

<script lang="ts"
        setup>
import type {Rule} from '@/assets/utils/validate'
import {computed, ref} from 'vue'

let emit = defineEmits<{
  (e: 'update:modelValue', v: any): void
}>()

let props = withDefaults(defineProps<{
  width?: string,
  labelWidth?: string,
  modelValue?: any,
  label?: string,
  placeholder?: string,
  type?: string,
  icon?: string,
  rules?: Rule[]
}>(), {
  width: '100%',
  type: 'text',
  placeholder: ''
})

defineExpose({
  judge
})

let inputValue = computed({
  get() {
    return props.modelValue
  },
  set(v: any) {
    emit('update:modelValue', v)
  }
})
let focus = ref<boolean>(false)
let errMsg = ref<string>('')

function judge(input: boolean = false): boolean {
  if (!props.rules?.length) return true
  for (let i in props.rules) {
    if (!props.rules[i].rule.test(inputValue.value ?? '')) {
      // 如果为input调用，则不改变errMsg值，只在验证成功时清除
      if (!input) errMsg.value = props.rules[i].msg
      return false
    }
  }
  errMsg.value = ''
  return true
}

function focusOut() {
  focus.value = false
  judge()
}
</script>

<style lang="less"
       scoped>
.input-box {
  display: flex;
  align-items: center;
  font-size: 14px;

  .label {
    color: #999999;
    padding-right: 10px;
    text-align: right;
  }

  .xtx-input {
    flex: 1;
    display: flex;
    height: 36px;
    border: 1px solid #cfcdcd;

    &.focus {
      border: 1px solid @xtxColor;
    }

    &.error {
      border: 1px solid @priceColor;
    }

    .left {
      width: 34px;
      background-color: #cfcdcd;
      display: flex;
      align-items: center;
      justify-content: center;

      i {
        font-size: 18px;
        color: white;
      }
    }

    .center {
      flex: 1;
      padding: 0 10px;
    }
  }
}

.err-msg {
  display: flex;
  height: 28px;
  line-height: 28px;
  font-size: 12px;
  color: @priceColor;

  .label {
    opacity: 0;
    color: #999999;
    padding-right: 10px;
    text-align: right;
  }

  .msg {
    flex: 1;
  }

  i {
    font-size: 14px;
  }
}
</style>